home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 27 / CU Amiga Magazine's Super CD-ROM 27 (1998)(EMAP Images)(GB)[!][issue 1998-10].iso / CUCD / Sound / SPlayer / Socks5 / src / lib / log.c < prev    next >
C/C++ Source or Header  |  1998-07-20  |  8KB  |  252 lines

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6.  
  7. /*
  8.  * $Id: log.c,v 1.71.4.2 1998/07/19 22:34:12 wlu Exp $
  9.  */
  10.  
  11. #define __NOLOGUPDATEPROTO
  12.  
  13. #include "socks5p.h"
  14.  
  15. #include "log.h"       /* Prototypes & defines.                              */
  16. #include "threads.h"   /* MUTEX & THREAD_SELF                                */
  17.  
  18. void *S5LogDefaultHandle = NULL;
  19. int   S5LogShowThreadIDS   = 0;
  20.  
  21. #ifdef HAVE_STDARG_H
  22. #include <stdarg.h>
  23. #define VA_START(a, b) va_start((a), (b))
  24. #define va_alist ...
  25. #define va_dcl
  26. #else
  27. #include <varargs.h>
  28. #define VA_START(a, b) va_start((a))
  29. #endif
  30.  
  31. #ifdef HAVE_NL_TYPES_H
  32. #include <nl_types.h>
  33. #endif
  34.  
  35. #ifdef HAVE_SYSLOG_H
  36. #include <syslog.h>
  37. #ifndef LOG_DAEMON
  38. #define LOG_DAEMON LOG_USER
  39. #endif
  40. #endif
  41.  
  42. typedef struct {
  43. #ifdef HAVE_NL_TYPES_H
  44.     nl_catd catalog;
  45. #define NL_START(x, y)     (x)->catalog = catopen((y), 0)
  46. #define NL_UPDATE(x, e, f) if ((x)->catalog != (nl_catd)-1) (f) = catgets((x)->catalog, 0, (e), (f))
  47. #define NL_CLOSE(x)        if ((x)->catalog != (nl_catd)-1) catclose((x)->catalog); (x)->catalog = (nl_catd)-1
  48. #elif defined(HAVE_DGETTEXT)
  49.     char domain[MAXNAMELEN];
  50. #define NL_START(x, y)     strncpy((x)->domain, name, MAX(MAXNAMELEN, strlen(name))); (x)->domain[MAX(MAXNAMELEN, strlen(name))] = '\0'
  51. #define NL_UPDATE(x, e, f) (f) = dgettext((x)->domain, (f))
  52. #define NL_CLOSE(x)
  53. #else
  54. #define NL_START(x, y) 
  55. #define NL_UPDATE(x, e, f) 
  56. #define NL_CLOSE(x)
  57. #endif
  58.     int level;
  59.     int how;
  60. } S5LogHandle;
  61.  
  62. static void replacePercentM(const char *inbuffer, char *outbuffer, int olen) {
  63.     register const char *t2;
  64.     register char *t1, ch;
  65.  
  66.     if (!outbuffer || !inbuffer) return;
  67.  
  68.     for (t1 = outbuffer; (ch = *inbuffer) && t1-outbuffer < olen ; ++inbuffer)
  69.     if (inbuffer[0] == '%' && inbuffer[1] == 'm') 
  70.         for (++inbuffer, t2 = strerror(GETERRNO()); (t2 && t1-outbuffer < olen) && (*t1 = *t2++); t1++);
  71.     else *t1++ = ch;
  72.     
  73.     *t1 = '\0';
  74. }
  75.  
  76. void S5LogvUpdate(const void *handle, int level, int msgID, const char *oformat, va_list pvar) {
  77. #define FMT_BUFLEN 2*1024 + 2*10
  78.     char fmt_cpy[FMT_BUFLEN], format[FMT_BUFLEN];
  79.     S5LogHandle *h = (S5LogHandle *)handle;
  80.     int serrno = GETERRNO();
  81. #ifndef VSNPRINTF
  82.     static FILE *tmpFile = NULL;
  83. #endif
  84.  
  85.     *fmt_cpy = '\0';
  86.  
  87.     /* If S5LogHandle has not been initialized, do it before we start;       */
  88.     /* Saves the mess of making sure it gets called ahead of time.           */
  89.     if (h == NULL) {
  90.     S5LogStart(&S5LogDefaultHandle, -1, -1, "libsocks5");
  91.     h = (S5LogHandle *)S5LogDefaultHandle;
  92.     }
  93.  
  94.     /* If the handle is invalid, don't log.                                  */
  95.     /* If the maximum log level is too low for this message, don't log.      */
  96.     /* If something that we call forces us to log a message, don't log.      */
  97.     if (!h || !(h->how) || h->level == -1 || level > h->level) return;
  98.  
  99.     /* Change the format if the message is in the catalog...                 */
  100.     NL_UPDATE(h, msgID, oformat);
  101.  
  102.     if (!oformat) return;
  103.  
  104.     /* Print the pid & maybe the thread id in format here.  Skip forward if  */
  105.     /* you don't want it later (e.g. if syslogging).                         */
  106.     sprintf(format, "%05d:", (int)getpid());
  107.     if (S5LogShowThreadIDS) sprintf(format+strlen(format), "%06d:", (int)THREAD_SELF());
  108.     strcat(format, " ");
  109.     
  110.     replacePercentM(oformat, format + strlen(format), sizeof(format) - strlen(format));
  111.  
  112. #ifdef HAVE_VSNPRINTF
  113.     if (vsnprintf(fmt_cpy, FMT_BUFLEN-1, format, pvar) < 0) {
  114.     fmt_copy[FMT_BUFLEN-1] = '\0';
  115.     }
  116. #else
  117.     /* Original idea for VSPRINTF verification courtesy of Sten Gunterbuer   */
  118.     /* (sten@ERGON.CH) a la BUGTRAQ.  Another solution is to use pipes or a  */
  119.     /* temp file, but I'm not convinced it would be more efficient (2 laps   */
  120.     /* through the formatting versus 1 and a bunch of byte copies through    */
  121.     /* the kernel).                                                          */
  122.     /*                                                                       */
  123.     /* Thanks to Zach Brown (zab@zabbo.net) for finding the problem...       */
  124.     if (tmpFile == NULL && (tmpFile = tmpfile()) == NULL) {
  125.     sprintf(fmt_cpy, "ERROR: Unable to verify string for vsprintf");
  126.     if ((h->level - 1) > S5_LOG_INFO) h->level = S5_LOG_INFO;
  127.     else h->level--;
  128.     level = S5_LOG_ERROR;
  129.     } else if (vfprintf(tmpFile, format, pvar) > FMT_BUFLEN-1) {
  130.     sprintf(fmt_cpy, "ERROR: String verification failed when trying to log message with format: %s", format);
  131.     if ((h->level - 1) > S5_LOG_INFO) h->level = S5_LOG_INFO;
  132.     else h->level--;
  133.     level = S5_LOG_ERROR;
  134.     } else {
  135.     rewind(tmpFile);
  136.     vsprintf(fmt_cpy, format, pvar);
  137.     }
  138. #endif
  139.  
  140.     /* Log to the Local log facility, e.g. Stderr on Unix and maybe a window */
  141.     /* or something on NT.  Neither system can deal with a NULL format so    */
  142.     /* check that here too.                                                  */
  143.     if (h->how & S5_LOG_LOCAL && format) {
  144.     fprintf(stderr, "%s\n", fmt_cpy);
  145.     fflush(stderr);
  146.     }
  147.  
  148.     /* Log to the system logging facility -- e.g. Syslog on Unix & the       */
  149.     /* EventLog on Windows NT.                                               */
  150.     if (h->how & S5_LOG_SYSTEM) {
  151. #if defined(HAVE_SYSLOG_H) && defined(SYSLOG_FAC)
  152.     int slfac, offset = 6; 
  153.  
  154.     if      (level == S5_LOG_ERROR)                  slfac = LOG_ERR;
  155.     else if (level == S5_LOG_INFO)                    slfac = LOG_NOTICE;
  156.     else if (level >  S5_LOG_INFO && level < S5_LOG_DEBUG(5))     slfac = LOG_WARNING;
  157.     else if (level >  S5_LOG_DEBUG(0) && level < S5_LOG_DEBUG(10))  slfac = LOG_NOTICE;
  158.     else if (level >  S5_LOG_DEBUG(5) && level < S5_LOG_DEBUG(15))  slfac = LOG_INFO;
  159.     else if (level >= S5_LOG_DEBUG(15))                slfac = LOG_DEBUG;
  160.  
  161.     /* skip "%05d:", and maybe another " "                               */
  162.     if (!S5LogShowThreadIDS) offset++;
  163.     syslog(slfac, fmt_cpy + offset);
  164. #else
  165. #endif
  166.     }
  167.  
  168.     SETERRNO(serrno); /* restore errno, just in case...?                     */
  169.     return;
  170. }
  171.  
  172. void  S5LogUpdate(const void *handle, int level, int msgID, const char *format, va_alist) va_dcl {
  173.     va_list pvar;
  174. #ifdef HAVE_STDARG_H
  175.     va_start(pvar, format);
  176. #else
  177.     VA_START(pvar, format);
  178. #endif
  179.     S5LogvUpdate(handle, level, msgID, format, pvar);
  180.     va_end(pvar);
  181. }
  182.  
  183. void S5LogStart(void **vhp, int how, int level, const char *name) {
  184.     S5LogHandle **hp = (S5LogHandle **)vhp;
  185.     char buf[1024], *tmp;
  186. /*
  187.     char tbuf[1024];
  188.     time_t now = time(NULL);
  189. */
  190.  
  191.     sprintf(buf, "%s", name);
  192.  
  193.     if (!(*hp) && ((*hp) = (S5LogHandle *)malloc(sizeof(S5LogHandle))) == NULL) {
  194.     /* no where to store things, so just skip it.                        */
  195.     return;
  196.     } else {
  197.     if (how == -1) {
  198.         (*hp)->how = 0;
  199.         if (getenv("SOCKS5_LOG_SYSLOG")) (*hp)->how |= S5_LOG_SYSTEM;
  200.          if (getenv("SOCKS5_LOG_STDERR")) (*hp)->how |= S5_LOG_LOCAL;
  201.     } else (*hp)->how = how;
  202.  
  203.     if (level == -1) {
  204.         if ((tmp = getenv("SOCKS5_DEBUG"))) {
  205.         if (isdigit((int)*tmp)) (*hp)->level = S5_LOG_DEBUG(atoi(tmp));
  206.             else (*hp)->level = S5_LOG_DEBUG(25);
  207.         } else (*hp)->level = -1;
  208.     } else (*hp)->level = level;
  209.  
  210.     NL_START(*hp, buf);
  211.  
  212.     }
  213.  
  214. #if defined(HAVE_SYSLOG_H) && defined(SYSLOG_FAC)
  215.     /* Only the first person to call this gets to open the log, that way the */
  216.     /* monitor doesn't clobber the server's socks5 name in the logs.         */
  217.     if ((*hp)->how & S5_LOG_SYSTEM){
  218.     static int logopened = 0;
  219.     
  220.     if (!logopened) {
  221.         logopened = 1;
  222.         openlog(name, LOG_PID, SYSLOG_FAC);
  223.     }
  224.     }
  225. #endif
  226.  
  227. /* Following code is commented out so that we can remove DontLoop...         */
  228. /*
  229.     if (restart && (*hp)->how != 0) {
  230.         MUTEX_LOCK(lt_mutex);
  231.         strftime(tbuf, sizeof(tbuf), "%c", REAL(localtime)(&now));
  232.         S5LogUpdate((*hp), S5_LOG_DEBUG(0), 0, "%s Logging (re)started at %s", name, tbuf);
  233.         MUTEX_UNLOCK(lt_mutex);
  234.     }
  235. */
  236. }
  237.  
  238. void S5LogEnd(void *vh) {
  239.     S5LogHandle *h = (S5LogHandle *)vh;
  240.  
  241.     if (!h) return;
  242.     NL_CLOSE(h);
  243.  
  244. #if defined(HAVE_SYSLOG_H) && defined(SYSLOG_FAC)
  245.     closelog();
  246. #endif
  247.  
  248.     
  249.     free(h);
  250. }
  251.  
  252.